﻿namespace ElisVK.Utils
{
    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.IO;
    using System.Linq;
    using System.Net;
    using System.Text;
    using System.Web;
    using System.Xml;
    using Data;

    public static class VKHelper
    {
        #region fields

        private static WebClient _webClient;

        #endregion fields

        #region Constructors
        
        #endregion Constructors

        #region Properties

        public static WebClient WebClient
        {
            get
            {
                if (_webClient == null)
                    _webClient = new WebClient();

                return _webClient;
            }
        }

        #endregion Properties

        #region Public Methods

        public static List<Audio> ParseRecommendationsPost(string page)
        {
            const string inputSplitter = "<input type=\"hidden\" id=\"audio_info";
            const string downloadUrlStart = "value=\"";
            const string downloadUrlEnd = ",";
            const string authorStart = "return false\">";
            const string authorEnd = "</a>";
            const string nameStart = "<span class=\"title\">";
            const string nameEnd = "</span>";
            const string lyricsMark = "Audio.showLyrics";

            var inputs = page.Split(new[] { inputSplitter }, StringSplitOptions.RemoveEmptyEntries);

            var audios = new List<Audio> { Capacity = inputs.Length };

            for (int i = 1; i < inputs.Length - 1; i++)
            {
                var input = inputs[i];

                var start = input.IndexOf(downloadUrlStart) + downloadUrlStart.Length;
                var downloadURL = input.Substring(start, input.IndexOf(downloadUrlEnd, start) - start);

                start = input.IndexOf(authorStart) + authorStart.Length;
                var author = input.Substring(start, input.IndexOf(authorEnd, start) - start);

                start = input.IndexOf(nameStart) + nameStart.Length;
                var name = input.Substring(start, input.IndexOf(nameEnd, start) - start);

                if (name.IndexOf(lyricsMark) != -1)
                {
                    start = name.IndexOf("\">") + 2;
                    name = name.Substring(start, name.IndexOf("</a>", start) - start);
                }

                var audio = new Audio
                {
                    DownloadURL = downloadURL,
                    Artist = HttpUtility.HtmlDecode(author.Trim()),
                    Title = HttpUtility.HtmlDecode(name.Trim())
                };

                audios.Add(audio);
            }

            return audios;
        }

        public static List<Audio> ParseAudiosFromXML(string data)
        {
            var audios = new List<Audio>();

            if (String.IsNullOrEmpty(data))
                return audios;

            var xmlDocument = new XmlDocument();

            xmlDocument.LoadXml(data);

            if (xmlDocument.ChildNodes.Cast<XmlNode>().Any(node => node.Name == "error"))
            {
                return audios;
            }

            var dataSet = new DataSet();

            dataSet.ReadXml(new StringReader(xmlDocument.InnerXml), XmlReadMode.InferSchema);

            if (dataSet.Tables["audio"] != null && dataSet.Tables["audio"].Rows.Count > 0)
            {
                foreach (DataRow dataRow in dataSet.Tables["audio"].Rows)
                {
                    audios.Add(new Audio(dataRow));
                }
            }

            return audios;
        }

        /// <summary> POST-запрос к Vkontakte </summary>    
        public static String PostRequest(String url, Cookie sidCookie)
        {
            //создаем запрос
            var wrPostURL = (HttpWebRequest)WebRequest.Create(url);

            wrPostURL.Method = "Post";
            wrPostURL.Headers["Cookie"] = sidCookie.ToString();

            var httpWebResponse = wrPostURL.GetResponse() as HttpWebResponse;

            if (httpWebResponse == null)
                return String.Empty;

            var responseStream = httpWebResponse.GetResponseStream();

            if (responseStream == null)
                return String.Empty;

            var myStreamReadermy = new StreamReader(responseStream, Encoding.GetEncoding(1251));
            var page = myStreamReadermy.ReadToEnd();

            return page;
        }

        public static byte[] DownloadData(string address)
        {
            return WebClient.DownloadData(address);
        }

        public static bool DownloadAudio(Audio audio, string path)
        {
            try
            {
                string sUrlToReadFileFrom = audio.DownloadURL;

                // the path to write the file to
                string sFilePathToWriteFileTo = AudioDownloader.GetPath(audio.FileNameForSave, path, true);

                if (File.Exists(sFilePathToWriteFileTo))
                    return true;


                // first, we need to get the exact size (in bytes) of the file we are downloading
                var url = new Uri(sUrlToReadFileFrom);
                var request = (HttpWebRequest) WebRequest.Create(url);
                //
                System.Net.HttpWebResponse response = (System.Net.HttpWebResponse)request.GetResponse();
                response.Close();
                // gets the size of the file in bytes
                Int64 iSize = response.ContentLength;

                // keeps track of the total bytes downloaded so we can update the progress bar
                Int64 iRunningByteTotal = 0;

                // use the webclient object to download the file
                using (System.Net.WebClient client = new System.Net.WebClient())
                {
                    // open the file at the remote URL for reading
                    using (System.IO.Stream streamRemote = client.OpenRead(new Uri(sUrlToReadFileFrom)))
                    {
                        // using the FileStream object, we can write the downloaded bytes to the file system
                        using (Stream streamLocal = new FileStream(sFilePathToWriteFileTo, FileMode.Create, FileAccess.Write, FileShare.None))
                        {
                            // loop the stream and get the file into the byte buffer
                            int iByteSize = 0;
                            byte[] byteBuffer = new byte[iSize];
                            while ((iByteSize = streamRemote.Read(byteBuffer, 0, byteBuffer.Length)) > 0)
                            {
                                // write the bytes to the file system at the file path specified
                                streamLocal.Write(byteBuffer, 0, iByteSize);
                                streamLocal.Flush();//
                                iRunningByteTotal += iByteSize;
                            }

                            // clean up the file stream
                            streamLocal.Close();
                        }

                        // close the connection to the remote server
                        streamRemote.Close();
                    }
                }
            }
            catch (Exception exc)
            {
            }

            return true;
        }
        
        #endregion Public Methods

        #region Private Methods



        #endregion Private Methods
    }
}
